package com.eagle.common.web.handler;

import com.eagle.common.core.constant.ResultCodeConstant;
import com.eagle.common.core.support.ResultMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.UnexpectedTypeException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author wcy
 * @date Created in 2021/9/14 14:11 <br>
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final String UNEXPECTED_TYPE_MESSAGE = "The annotation format does not match in the verification ！！";


    /**
     * Business exception handler result message.
     * 校验异常捕获,统一返回
     *
     * @param e the exception
     * @return the result message
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResultMessage constraintViolationException(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        String messages = constraintViolations.stream().map(constraintViolation -> constraintViolation.getMessage()).reduce((s, s2) -> s + "," + s2).get();
        log.info(e.toString(), e.getCause());

        return ResultMessage.error(ResultCodeConstant.BUSINESS_SERVICE_CODE, messages);
    }

    /**
     * Business exception handler result message.
     * 校验异常捕获,统一返回
     *
     * @param e the exception
     * @return the result message
     */
    @ExceptionHandler(value = UnexpectedTypeException.class)
    public ResultMessage unexpectedTypeException(UnexpectedTypeException e) {
        log.info(e.toString(), e.getCause());
        return ResultMessage.builder().message(UNEXPECTED_TYPE_MESSAGE).build();
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResultMessage methodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error(e.toString(), e);
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        List<String> messages = errors.stream().map(error -> error.getDefaultMessage()).collect(Collectors.toList());

        return ResultMessage.builder().message(messages).build();
    }

    @ExceptionHandler(value = RuntimeException.class)
    public ResultMessage runtimeExceptionHandler(RuntimeException e) {
        log.error(e.toString(), e);
        return ResultMessage.builder().message(e.getMessage()).build();
    }

    @ExceptionHandler(value = Exception.class)
    public ResultMessage otherExceptionHandler(Exception e) {
        log.error(e.toString(), e);
        return ResultMessage.builder().message(e.getMessage()).build();
    }

}